// Copyright 2010, Vanya Davidenko.
// Используемая кодировка: UTF-8.

#ifndef SCRW_TYPES_H_
#define SCRW_TYPES_H_

#include <ctime>
#include <string>
#include <vector>
#include <iostream>

#include <libv/cast.h>
#include <libv/check.h>
#include <libv/cistring.h>
#include <libv/lock.h>
#include <libv/lock_spin.h>

#include <unicode/unistr.h>

#define I32(x) libv::IntegerCast<int32_t>(x)
#define UI32(x) libv::IntegerCast<uint32_t>(x)
#define MSG(expr) {  if ( g_verbose_level >= 2 )                           \
                     {                                                     \
                         libv::Lock console_lock(&g_console_lock);         \
                         ::std::cout << "[ ] "                             \
                                     << FormattedTime("%Y-%m-%d %H:%M:%S") \
                                     << " "                                \
                                     << expr                               \
                                     << ::std::endl;                       \
                     }  }

#define LOG(expr) {  if ( g_verbose_level >= 1 )                           \
                     {                                                     \
                         libv::Lock console_lock(&g_console_lock);         \
                         ::std::cout << "[.] "                             \
                                     << FormattedTime("%Y-%m-%d %H:%M:%S") \
                                     << " "                                \
                                     << expr                               \
                                     << ::std::endl;                       \
                     }  }

#define ERR(expr) {  if ( g_verbose_level >= 0 )                           \
                     {                                                     \
                         libv::Lock console_lock(&g_console_lock);         \
                         ::std::cout << "[!] "                             \
                                     << FormattedTime("%Y-%m-%d %H:%M:%S") \
                                     << " "                                \
                                     << expr                               \
                                     << ::std::endl;                       \
                     }  }


namespace scrw
{
    extern libv::Spin g_console_lock;
    extern int g_verbose_level;

    typedef libv::CIString MimeType;
    typedef libv::CIString Charset;
    typedef libv::CIString FileExtension;

    typedef icu::UnicodeString Html;
    typedef icu::UnicodeString Tag;

    typedef icu::UnicodeString UnicodeUrl;
    typedef icu::UnicodeString UAsciiUrl;
    typedef ::std::string AsciiUrl;


    /** Преобразование юникодной строки в стандартную в заданной кодировке.
      * При передаче NULL в качестве второго аргумента используется
      * системная кодировка. */
    inline ::std::string UnicodeString2String(const icu::UnicodeString& s,
                                              const char* codepage = NULL)
    {
        PRECOND(s.isBogus() == FALSE);
        if ( s.isEmpty() )
            return ::std::string();

        ::std::vector<char> v_str(1);
        const int32_t len = s.extract(0, s.length(), &v_str[0], 1, codepage);

        v_str.resize(len + 1);
        const int32_t act_len = s.extract(0, s.length(), &v_str[0], codepage);
        VERIFY(act_len + 1 == I32(v_str.size()));

        return ::std::string(&v_str[0], act_len);
    }


    inline ::std::string FormattedTime(const char* fmt)
    {
        const time_t timestamp = ::std::time(NULL);
        struct tm timeinfo;
#ifdef _WIN32
        VERIFY(localtime_s(&timeinfo, &timestamp) == 0);
#else
        VERIFY(localtime_r(&timestamp, &timeinfo) == &timeinfo);
#endif
        char buffer[1024];
        const size_t size = strftime(buffer, sizeof(buffer), fmt, &timeinfo);
        return ::std::string(buffer, size);
    }
}

#endif  // SCRW_TYPES_H_
